'use strict'

class Digger {

    constructor(options = {}) {
        // private members
        this._cfg = options;
        this._tags = new Array();
        this._originalAddrList = new Array();
        this._content = '';
        this._curPos = 0;
        this._curTag = '';
    }

    dig(content) {

        this._content = content;

        while (this._findPartNext()) {
            this._keepClear();

            if (this._isValid()) {
                this._analyze();
            }
        }
    }

    tags() { return this._tags; }

    originalAddrList() { return this._originalAddrList; }


    /**
     * 
     * Private functions
     * 
     */

    _findPartNext() {
        const result = this._findPart(this._content, this._curPos, this._content.length, this._cfg.begin, this._cfg.end);

        if (result) {
            this._tags.push(result.value);
            this._curPos = result.pos;
            this._curTag = result.value;
            return true;
        }

        return false;
    }

    _findPart(findInContent, pos, limit, begin, end) {
        const tryGetPos = (str, pos) => {
            while (pos < limit) {
                if (findInContent.substr(pos, str.length) === str) {
                    return pos;
                } else {
                    pos += 1;
                }
            }

            return null;
        }

        const bPos = tryGetPos(begin, pos);
        const ePos = tryGetPos(end, bPos + begin.length);

        if (bPos != null && ePos != null) {
            const newPos = ePos + end.length;
            const val = findInContent.substr(bPos, (ePos - bPos + 1));

            return {
                value: val,
                pos: newPos
            };
        }

        return null;
    }

    _keepClear() {
        this._curTag = this._curTag.replace(new RegExp(this._cfg.clear, 'g'), '');
    }

    _isValid() {
        let check = true;

        if (this._cfg.ignoreTag) {
            this._cfg.ignoreTag.forEach((item) => {
                if (this._curTag.substr(0, item.length) === item) {
                    check = false;
                }
            });
        }

        if (check && this._cfg.ignoreTagUnless) {
            let isBegin = true;
            let matched = false;
            let matchTag = null;
            let matchVal = null;

            this._cfg.ignoreTagUnless.forEach((item) => {
                if (isBegin) {
                    isBegin = false;
                    matched = false;

                    if (this._curTag.substr(0, item.length) === item) {
                        matched = true;
                        matchTag = true;
                    }
                } else {
                    isBegin = true;

                    if (matched && this._curTag.match(new RegExp(item))) {
                        matchVal = true;
                    }
                }
            });

            if (matchTag && !matchVal) {
                check = false;
            }
        }

        if (check && this._cfg.ignoreProp) {
            this._cfg.ignoreProp.forEach((item) => {
                if (this._curTag.match(new RegExp(item))) {
                    check = false;
                }
            });
        }

        return check;
    }

    _analyze() {
        let result = '';
        let lastItem = null;

        this._cfg.findProp.forEach((item) => {
            if (!lastItem) {
                lastItem = item;
            } else {
                result = this._findPart(this._curTag, 0, this._curTag.length, lastItem, item);

                if (result) {
                    result.value = result.value.substr(lastItem.length);
                    result.value = result.value.substr(0, result.value.length - item.length);

                    if (result.value.trim().length > 0 && this._originalAddrList.indexOf(result.value) === -1) {
                        this._originalAddrList.push(result.value);
                    }
                }
                lastItem = null;
            }
        });
    }

}

module.exports = Digger;

// module.exports = {
//     reset: reset,
//     config: config,
//     dig: dig,
//     tags: () => { return tags; },
//     originalAddrList: () => { return originalAddrList; }
// }
